#include "alarm_module.h"
#include "temp_module.h"
#include "adc_module.h"
#include "flow_module.h"
#include "water_module.h"
#include "log_module.h"

static alarm_config_t *alarm_config = RT_NULL;
static rt_thread_t alarm_thread = RT_NULL;

/* Alarm monitoring function */
static rt_err_t check_temperature_alarms(void)
{
    float temperature;
    rt_bool_t triggered;
    
    for (int i = 0; i < 4; i++) {
        if (i >= MAX_ALARMS) break;
        
        if (!alarm_config->alarms[i].enabled) continue;
        
        temperature = temp_get_temperature(i);
        triggered = RT_FALSE;
        
        /* Check high limit */
        if (temperature > alarm_config->alarms[i].high_limit) {
            triggered = RT_TRUE;
        }
        /* Check low limit */
        else if (temperature < alarm_config->alarms[i].low_limit) {
            triggered = RT_TRUE;
        }
        
        /* Update alarm state */
        if (triggered && !alarm_config->alarms[i].triggered) {
            /* Alarm triggered */
            alarm_config->alarms[i].triggered = RT_TRUE;
            alarm_config->alarms[i].trigger_time = rt_tick_get();
            
            /* Send alarm message */
            alarm_info_t alarm_info = {
                .type = (i == 0) ? ALARM_TEMPERATURE_HIGH : ALARM_TEMPERATURE_LOW,
                .level = alarm_config->alarms[i].level,
                .channel = i,
                .value = temperature,
                .limit = triggered ? alarm_config->alarms[i].high_limit : alarm_config->alarms[i].low_limit,
                .triggered = RT_TRUE,
                .timestamp = rt_tick_get()
            };
            
            send_message(MODULE_LOG, MSG_ALARM_TRIGGER, &alarm_info, sizeof(alarm_info));
            
            LOG_W("Temperature alarm triggered: channel=%d, value=%.1f, limit=%.1f\n", 
                  i, temperature, alarm_info.limit);
        }
        else if (!triggered && alarm_config->alarms[i].triggered) {
            /* Alarm cleared */
            alarm_config->alarms[i].triggered = RT_FALSE;
            
            LOG_I("Temperature alarm cleared: channel=%d\n", i);
        }
    }
    
    return RT_OK;
}

static rt_err_t check_pressure_alarms(void)
{
    float pressure;
    rt_bool_t triggered;
    
    /* Pressure alarms use ADC channels (assuming pressure transducers on 4-20mA) */
    for (int i = 0; i < 4; i++) {
        int alarm_index = i + 4;  /* Pressure alarms start from index 4 */
        if (alarm_index >= MAX_ALARMS) break;
        
        if (!alarm_config->alarms[alarm_index].enabled) continue;
        
        pressure = adc_get_engineering_value(i);
        triggered = RT_FALSE;
        
        /* Check high limit */
        if (pressure > alarm_config->alarms[alarm_index].high_limit) {
            triggered = RT_TRUE;
        }
        /* Check low limit */
        else if (pressure < alarm_config->alarms[alarm_index].low_limit) {
            triggered = RT_TRUE;
        }
        
        /* Update alarm state */
        if (triggered && !alarm_config->alarms[alarm_index].triggered) {
            alarm_config->alarms[alarm_index].triggered = RT_TRUE;
            alarm_config->alarms[alarm_index].trigger_time = rt_tick_get();
            
            alarm_info_t alarm_info = {
                .type = ALARM_PRESSURE_HIGH,
                .level = alarm_config->alarms[alarm_index].level,
                .channel = i,
                .value = pressure,
                .limit = triggered ? alarm_config->alarms[alarm_index].high_limit : alarm_config->alarms[alarm_index].low_limit,
                .triggered = RT_TRUE,
                .timestamp = rt_tick_get()
            };
            
            send_message(MODULE_LOG, MSG_ALARM_TRIGGER, &alarm_info, sizeof(alarm_info));
            
            LOG_W("Pressure alarm triggered: channel=%d, value=%.1f, limit=%.1f\n", 
                  i, pressure, alarm_info.limit);
        }
        else if (!triggered && alarm_config->alarms[alarm_index].triggered) {
            alarm_config->alarms[alarm_index].triggered = RT_FALSE;
            LOG_I("Pressure alarm cleared: channel=%d\n", i);
        }
    }
    
    return RT_OK;
}

static rt_err_t check_flow_alarms(void)
{
    float flow_rate;
    rt_bool_t triggered;
    
    for (int i = 0; i < 2; i++) {
        int alarm_index = i + 8;  /* Flow alarms start from index 8 */
        if (alarm_index >= MAX_ALARMS) break;
        
        if (!alarm_config->alarms[alarm_index].enabled) continue;
        
        flow_rate = flow_get_flow_rate(i);
        triggered = RT_FALSE;
        
        /* Check high limit */
        if (flow_rate > alarm_config->alarms[alarm_index].high_limit) {
            triggered = RT_TRUE;
        }
        /* Check low limit */
        else if (flow_rate < alarm_config->alarms[alarm_index].low_limit) {
            triggered = RT_TRUE;
        }
        
        /* Update alarm state */
        if (triggered && !alarm_config->alarms[alarm_index].triggered) {
            alarm_config->alarms[alarm_index].triggered = RT_TRUE;
            alarm_config->alarms[alarm_index].trigger_time = rt_tick_get();
            
            alarm_info_t alarm_info = {
                .type = ALARM_FLOW_HIGH,
                .level = alarm_config->alarms[alarm_index].level,
                .channel = i,
                .value = flow_rate,
                .limit = triggered ? alarm_config->alarms[alarm_index].high_limit : alarm_config->alarms[alarm_index].low_limit,
                .triggered = RT_TRUE,
                .timestamp = rt_tick_get()
            };
            
            send_message(MODULE_LOG, MSG_ALARM_TRIGGER, &alarm_info, sizeof(alarm_info));
            
            LOG_W("Flow alarm triggered: channel=%d, value=%.1f, limit=%.1f\n", 
                  i, flow_rate, alarm_info.limit);
        }
        else if (!triggered && alarm_config->alarms[alarm_index].triggered) {
            alarm_config->alarms[alarm_index].triggered = RT_FALSE;
            LOG_I("Flow alarm cleared: channel=%d\n", i);
        }
    }
    
    return RT_OK;
}

static rt_err_t alarm_check_all(void)
{
    rt_err_t result;
    
    result = check_temperature_alarms();
    if (result != RT_OK) return result;
    
    result = check_pressure_alarms();
    if (result != RT_OK) return result;
    
    result = check_flow_alarms();
    
    return result;
}

static void process_alarm_message(message_t *msg)
{
    if (msg == RT_NULL) return;
    
    switch (msg->msg_type) {
        case MSG_DATA_UPDATE:
            /* New data available, check alarms */
            alarm_check_all();
            break;
            
        case MSG_CONTROL_CMD:
            if (msg->data != RT_NULL) {
                /* Handle alarm control commands */
                uint8_t *cmd = (uint8_t *)msg->data;
                if (*cmd == CMD_RESET) {
                    /* Reset all alarms */
                    for (int i = 0; i < MAX_ALARMS; i++) {
                        alarm_config->alarms[i].triggered = RT_FALSE;
                    }
                }
            }
            break;
            
        default:
            break;
    }
}

rt_err_t alarm_module_init(void)
{
    /* Get configuration pointer */
    alarm_config = &g_system_config.alarm;
    
    /* Create alarm thread */
    alarm_thread = rt_thread_create("alarm", 
                                   alarm_thread_entry, 
                                   RT_NULL, 
                                   1024, 
                                   17, 
                                   20);
    if (alarm_thread == RT_NULL) {
        LOG_E("Failed to create alarm thread\n");
        return RT_ERR_MEM;
    }
    
    LOG_I("Alarm module initialized successfully\n");
    return RT_OK;
}

void alarm_thread_entry(void *parameter)
{
    rt_uint32_t tick;
    
    while (1) {
        tick = rt_tick_get();
        
        if (alarm_config->base.enabled) {
            /* Check all alarms */
            alarm_check_all();
        }
        
        /* Wait for next check cycle */
        rt_thread_delay_until(&tick, rt_tick_from_millisecond(alarm_config->base.update_interval));
    }
}

rt_err_t alarm_acknowledge(uint8_t alarm_index)
{
    if (alarm_index >= MAX_ALARMS || alarm_config == RT_NULL) {
        return RT_ERR_PARAM;
    }
    
    alarm_config->alarms[alarm_index].acknowledge_time = rt_tick_get();
    
    LOG_I("Alarm %d acknowledged\n", alarm_index);
    
    return RT_OK;
}

rt_err_t alarm_set_limits(uint8_t alarm_index, float low_limit, float high_limit, alarm_level_t level)
{
    if (alarm_index >= MAX_ALARMS || alarm_config == RT_NULL) {
        return RT_ERR_PARAM;
    }
    
    alarm_config->alarms[alarm_index].low_limit = low_limit;
    alarm_config->alarms[alarm_index].high_limit = high_limit;
    alarm_config->alarms[alarm_index].level = level;
    alarm_config->alarms[alarm_index].enabled = RT_TRUE;
    
    LOG_I("Alarm %d limits set: low=%.1f, high=%.1f, level=%d\n", 
          alarm_index, low_limit, high_limit, level);
    
    return RT_OK;
}

rt_uint32_t alarm_get_active_count(void)
{
    rt_uint32_t count = 0;
    
    if (alarm_config == RT_NULL) {
        return 0;
    }
    
    for (int i = 0; i < MAX_ALARMS; i++) {
        if (alarm_config->alarms[i].triggered) {
            count++;
        }
    }
    
    return count;
}

rt_bool_t alarm_is_triggered(uint8_t alarm_index)
{
    if (alarm_index >= MAX_ALARMS || alarm_config == RT_NULL) {
        return RT_FALSE;
    }
    
    return alarm_config->alarms[alarm_index].triggered;
}

alarm_config_t *alarm_get_config(void)
{
    return alarm_config;
}